/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "wizchip_conf.h"
#include <string.h>
#include <stdio.h>
#include "loopback.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t  gDATABUF[16384];
static uint8_t SSIZE[8]= {4,4,4,4,0,0,0,0}; /**< Max Tx buffer size by each channel */
static uint8_t RSIZE[8]= {4,4,4,4,0,0,0,0}; /**< Max Rx buffer size by each channel */

static void w5500_hard_rst(void)
{
	HAL_GPIO_WritePin(W5500_RESET_GPIO_Port, W5500_RESET_Pin, GPIO_PIN_RESET);
	HAL_Delay(2);
	HAL_GPIO_WritePin(W5500_RESET_GPIO_Port, W5500_RESET_Pin, GPIO_PIN_SET);
	HAL_Delay(10);
}

static int w5500_chip_init(void)
{
    /* default size is 2KB */
    //return wizchip_init(NULL, NULL);
		return wizchip_init(SSIZE, RSIZE);
}

static void w5500_phy_init(void)
{
    wiz_PhyConf conf;

    conf.by = PHY_CONFBY_SW;		//1
    conf.mode = PHY_MODE_MANUAL;	//0
    conf.speed = PHY_SPEED_100;		//1
    conf.duplex = PHY_DUPLEX_FULL;	//1

    wizphy_setphyconf(&conf);
    HAL_Delay(10);


    wiz_PhyConf phyconf;
    ctlwizchip(CW_GET_PHYCONF, (void*)&phyconf);
    if(memcmp(&conf,&phyconf,sizeof(wiz_PhyConf)) == 0){
      printf("set phy parameters success\r\n");// 配置成功
    }else{
      printf("set phy parameters fail\r\n"); // 配置失败
    }
    printf("by =%d;mode =%d;speed =%d;duplex =%d\n",phyconf.by,phyconf.mode,phyconf.speed,phyconf.duplex);

    uint8_t phylink;
    uint8_t phymode;
    ctlwizchip(CW_GET_PHYPOWMODE, (void*)&phymode);//PHY_POWER_NORM = 0,PHY_POWER_DOWN = 1
    printf("phymode = %d\n",phymode);
    ctlwizchip(CW_GET_PHYLINK, (void*)&phylink);//PHY_LINK_OFF = 0,PHY_LINK_ON = 1
    printf("phylink = %d\n",phylink);

    uint8_t version;
    version = getVERSIONR();
    printf("version = %d\n",version);

}

static void w5500_network_info_init(void)
{
    wiz_NetInfo info;

    uint8_t mac[6] = {0x00,0xf1,0xbe,0xc4,0xa1,0x05};
    uint8_t ip[4] = {192,168,1,110};
    uint8_t sn[4] = {255,255,255,0};
    uint8_t gw[4] = {192,168,1,1};
    uint8_t dns[4] = {0,0,0,0};

    memcpy(info.mac, mac, 6);
    memcpy(info.ip, ip, 4);
    memcpy(info.sn, sn, 4);
    memcpy(info.gw, gw, 4);
    memcpy(info.dns, dns, 4);

    info.dhcp = NETINFO_STATIC;

    wizchip_setnetinfo(&info);
}

void w5500_network_info_show(void)
{
    wiz_NetInfo info;

    wizchip_getnetinfo(&info);

    printf("w5500 network infomation:\r\n");
    printf("  -mac:%x:%x:%x:%x:%x:%x\r\n", info.mac[0], info.mac[1], info.mac[2],
            info.mac[3], info.mac[4], info.mac[5]);
    printf("  -ip:%d.%d.%d.%d\r\n", info.ip[0], info.ip[1], info.ip[2], info.ip[3]);
    printf("  -sn:%d.%d.%d.%d\r\n", info.sn[0], info.sn[1], info.sn[2], info.sn[3]);
    printf("  -gw:%d.%d.%d.%d\r\n", info.gw[0], info.gw[1], info.gw[2], info.gw[3]);
    printf("  -dns:%d.%d.%d.%d\r\n", info.dns[0], info.dns[1], info.dns[2], info.dns[3]);

    if (info.dhcp == NETINFO_DHCP) {
        printf("  -dhcp_mode: dhcp\r\n");
    } else {
        printf("  -dhcp_mode: static\r\n");
    }
}

int w5500_init(void)
{
	w5500_hard_rst();
	 /* Register spi driver function */
	w5500_regFunc();

	/* socket buffer size init */
	if (w5500_chip_init() != 0) {
		return -1;
	}

	/* phy init */
	w5500_phy_init();

	/* network infomation init */
	w5500_network_info_init();

	/* show network infomation */
	w5500_network_info_show();

	return 0;
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI4_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	printf("w5500 project\n");

	int ret;
	ret = w5500_init();
	if (ret != 0) {
		printf("w5500 init fail, ret is %d\r\n", ret);
	} else {
		printf("w5500 init success\r\n");
	}
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	int32_t ret = 0;

	if( (ret = loopback_tcps(0, gDATABUF, 5000)) < 0) {
		printf("SOCKET ERROR : %ld\r\n", ret);
	}
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 360;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
